package com.bootcamp.s2_0922.ds.Exercise._0929_Ex;

import java.util.Arrays;
import java.util.List;
import java.util.ListIterator;

/**
 * @program: myClassCode
 * @description: implement iterator or listitertor in MyArrayList
 * @author: Keyu Li
 * @create: 2021-09-29 20:42
 **/

public class Ex3_MyIterator {
    public static void main(String[] args) {
        MyArrayList<String> list = new MyArrayList<>();
        list.add("ws001");
        list.add("ws002");
        list.add("ws003");
        list.add("ws004");
        list.add("ws004");
        list.add("ws005");
        list.add("ws005");
        list.add("ws005");
        list.add("ws006");
        list.add("ws006");
        list.add("ws006");
        list.add("ws007");
        list.add("ws008");
        list.add("ws009");

        ListIterator<String> iterator = list.listIterator();
        while (iterator.hasNext()) {
            System.out.println(iterator.next());
        }
        System.out.println("-----------------");
        ListIterator<String> iteratorPre = list.listIterator(1);
        while (iteratorPre.hasPrevious()) {
            System.out.println(iteratorPre.previous());
        }
    }
}

class MyArrayList<T> {
    public static final int MAX_CAPACITY = Integer.MAX_VALUE - 8;
    public static final int DEFAULT_CAPACITY = 8;
    private int size;
    Object[] values;

    public MyArrayList() {
        values = new Object[DEFAULT_CAPACITY];
    }

    public MyArrayList(int capacity) {
        if (capacity <= 0 || capacity > MAX_CAPACITY) throw new RuntimeException("array capacity out of range!");
        values = new Object[capacity];
    }

    // 返回 listIterator 对象
    public ListIterator<T> listIterator() {
        return new Iter();
    }

    // 有参方法，从 index位置(开区间)开始遍历
    public ListIterator<T> listIterator(int index) {
        return new Iter(index);
    }

    // 私有 LIter类，实现listInterator接口
    private class Iter implements ListIterator {
        private int lastRet;
        private int cursor;

        public Iter() {
            cursor = 0;
            lastRet = -1;
        }

        public Iter(int index) {
            if (index <= 0 || index > MyArrayList.this.size)
                throw new RuntimeException("index out of range!");
            cursor = index;
            lastRet = -1;
        }

        @Override
        public boolean hasNext() {
            return cursor != MyArrayList.this.size;
        }

        @Override
        public Object next() {
            lastRet = cursor;
            return MyArrayList.this.get(cursor++);
        }

        @Override
        public boolean hasPrevious() {
            return cursor != 0;
        }

        @Override
        public Object previous() {
            cursor--;
            lastRet = cursor;
            return MyArrayList.this.get(cursor);
        }

        @Override
        public int nextIndex() {
            return cursor;
        }

        @Override
        public int previousIndex() {
            return cursor - 1;
        }

        @Override
        public void remove() {
            MyArrayList.this.remove(lastRet);
            cursor = lastRet;
            lastRet = -1;
        }

        @Override
        public void set(Object o) {
            MyArrayList.this.set(lastRet, (T) o);
        }

        @Override
        public void add(Object o) {
            MyArrayList.this.add(cursor, (T) o);
            cursor++;
            lastRet = -1;
        }
    }


    // 判断数组是否为空
    public boolean isEmpty() {
        return size == 0;
    }

    // 判断传入元素是否合法
    private void elementJudge(T element) {
        if (element == null) throw new RuntimeException("illegal input element!");
    }

    // 判断是否需要进行容量调整
    private boolean resize(int minNewCapacity) {
        if (minNewCapacity >= values.length) {
            expand(minNewCapacity);
        }
        return true;
    }

    // 扩容：当已经无空位时，新数组是原数组2倍长度。
    private boolean expand(int minNewCapacity) {
        if (minNewCapacity > MAX_CAPACITY) throw new RuntimeException("capacity out of range!");
        int newCapacity = minNewCapacity << 1;
        if (newCapacity < 0 || newCapacity > MAX_CAPACITY)
            newCapacity = MAX_CAPACITY;

        Object[] newValues = new Object[newCapacity];
        for (int i = 0; i < size; i++) {
            newValues[i] = values[i];
        }
        values = newValues;
        return true;
    }

    // 缩容：当实际使用容量小于数组长度 1/4
    private boolean shrink(int minNewCapacity) {
        // 该方法是否需要存疑
        return true;
    }

    // 整理：剔除数组内空元素
    private boolean settle() {
        int count = 0;
        for (int i = 0; i < size; i++) {
            if (values[i] == null)
                count++;
            values[i] = values[i + count];
        }
        size -= count;
        return true;
    }

    // 整理：剔除index位置
    private boolean settle(int index) {
        for (int i = index; i < size - 1; i++) {
            values[i] = values[i + 1];
        }
        size--;
        return true;
    }

    // 添加新value
    public boolean add(T element) {
        elementJudge(element);
        resize(size + 1);
        values[size] = element;
        size++;
        return true;
    }

    // 传入value，查找成功返回index，失败-1
    public int get(T element) {
        elementJudge(element);
        for (int i = 0; i < size; i++) {
            // 默认已经重写了 equals 方法
            if (element.equals(values[i]))
                return i;
        }
        return -1;
    }

    // 传入value，删除
    public boolean remove(T element) {
        elementJudge(element);
        if (isEmpty()) throw new RuntimeException("empty array exception!");
        int i = 0;
        for (; i < size; i++) {
            // 默认已经重写了 equals 方法
            if (element.equals(values[i]))
                break;
        }
        if (i == size) return false;
        settle(i);
        resize(size);
        return true;
    }

    // 传入value，修改
    public boolean set(T newValue) {
        elementJudge(newValue);
        int i = 0;
        for (; i < size; i++) {
            // 默认已经重写了 equals 方法
            if (newValue.equals(values[i]))
                break;
        }
        if (i == size) return false;
        values[i] = newValue;
        return true;
    }

    // 指定下标，添加新value
    public boolean add(int index, T element) {
        elementJudge(element);
        if (index < 0 || index > size) throw new RuntimeException("insert index out of range!");
        resize(size + 1);
        for (int i = size; i > index; i--) {
            values[i] = values[i - 1];
        }
        values[index] = element;
        return true;
    }

    // 传入index，查找
    public T get(int index) {
        if (index < 0 || index > size - 1) throw new RuntimeException("index out of range!");
        return ((T) values[index]);
    }

    // 传入index，删除
    public boolean remove(int index) {
        if (isEmpty()) throw new RuntimeException("empty array exception!");
        if (index < 0 || index > size - 1) throw new RuntimeException("index out of range!");
        settle(index);
        resize(size);
        return true;
    }

    // 传入index，修改
    public boolean set(int index, T newValue) {
        elementJudge(newValue);
        if (index < 0 || index > size - 1) throw new RuntimeException("index out of range!");
        values[index] = newValue;
        return true;
    }

    // toString
    @Override
    public String toString() {
        final StringBuffer sb = new StringBuffer("MyArrayList{");
        sb.append("size=").append(size);
        sb.append(", values=").append(values == null ? "null" : Arrays.asList(values).toString());
        sb.append('}');
        return sb.toString();
    }
}